#fastapi做的文件服务器
#python3 -m uvicorn fastapi0:app --host "0.0.0.0" --port 82 --reload
from fastapi import FastAPI
from fastapi import FastAPI,Form
from starlette.responses import HTMLResponse
from starlette.responses import RedirectResponse
import uvicorn
from pyecharts import options as opts
import json
import os
from pyecharts.components import Table
from pyecharts.options import ComponentTitleOpts
from tinydb import TinyDB, Query
from fastapi import Cookie, FastAPI
from typing import Optional
from starlette.responses import Response

#表格

def tab_html(title,headers0,rows):
    start='''
    <table class="table table-condensed">
        <thead>
            <tr>
                <th>#</th>
                <th>Firstname</th>
                <th>2nname</th>
            </tr>
        </thead>
        '''
    headers='<body><h2>'+title+'</h2><table class="table table-bordered table-striped"><thead><tr>'
    for item in headers0:
        headers=headers+'<th>'+item+'</th>'
    headers=headers+'</tr></thead>'
    body='<tbody>'
    i=1
    for item in rows:
        body=body+'<tr>'
        #i=1
        for x in item:
            body=body+'<td><a href="{}?q={}">{}</a>'.format(title,i,str(x))+'</td>'
        i=i+1
        body=body+'</tr>'
    body=body+'</tbody></table></body>'
    return headers+body

 


#批量excel导入的模板
import1='''
<html>
<body>
    <form action="/db/" name="ok" method="post">
 
       <div class="layui-form-item layui-form-text">
       表名:{name}
       <input type="text" name="fname" value={name}>
            <div><label class="layui-form-label">批量导入，从excel表复制过来粘贴，必须包含表头,第一列值不能重复</label><div>
            <div class="layui-input-block">
              <textarea rows="20" cols="150" placeholder="请输入内容" name=fname1 class="layui-textarea"></textarea>
            </div>
          </div>
          <input type="submit" value="提交" />
    </form>
</body>
</html>
'''

 
#html头部
html_head='''

<html>

  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面，任何其他内容都*必须*跟随其后！ -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询（media queries）功能 -->
    <!-- 警告：通过 file:// 协议（就是直接将 html 页面拖拽到浏览器中）访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    <![endif]-->
  </head>

<body>
'''


json_form='''

     <form action="/json/" name="ok" method="post">
 
       <div class="layui-form-item layui-form-text">
       <input type="hidden" name="fname" value={name}>
            <div class="layui-input-block">
              <textarea rows="20" cols="180" placeholder="请输入内容" name=fname1 class="layui-textarea" value="abc">{json}</textarea>
            </div>
          </div>
          <input type="submit" name="action" value="提交修改" /><input type="submit" name="action" value="删除" />
    </form>
'''

 


 

app = FastAPI()

 

 



#批量更新表单
@app.get("/tables_new/{item_id}")
def b0(item_id:str=None):
    if item_id:
        return HTMLResponse(content=import1.format(name=item_id))
    else:
        return HTMLResponse(content=import1.format(name=''))

#新建表单
@app.get("/tables_new/")
def b00(item_id:str=None):
    if item_id:
        return HTMLResponse(content=import1.format(name=item_id))
    else:
        return HTMLResponse(content=import1.format(name=''))

#批量excel导入 
@app.post("/db/")

def b2(fname1:str=Form(...),fname:str=Form(...),username: Optional[str] = Cookie(None)):
    #print('fname',fname)
    #print('running db')
    if username in userlist:
        pass
    else:
        return RedirectResponse(url='/login')   


    print(fname1,type(fname1))
    #dict0=eval(fname1)
    #print(dict0)
    list0=fname1.split('\r\n')
    headers=list0[0].split('\t')
    rows0=list(filter(lambda x:x!="",list0[1:]))
    #print('rows0:',rows0)
   
    rows=list(map(lambda x:x.split('\t'),rows0))
    #print("headers:",headers)
    #print('rows:',rows)
    db = TinyDB('db/'+fname+'.json')

    User = Query()
    #keys=list(dict0.keys())
    #values=list(dict0.values())
    for row in rows:
        x=dict(zip(headers,row))
        if db.search(User[headers[0]] == row[0]):
            db.update(x, User[headers[0]] == row[0])
        else:
            
        #print("-------------",db.search(User.headers[0] == row0))
        #print(x)
            db.insert(x)
    db.close()
    return RedirectResponse(url='/ok/'+fname)

#更新单个条目的json
@app.post("/json/")

def b2(fname1:str=Form(...),fname:str=Form(...),action:str=Form(...),username: Optional[str] = Cookie(None)):
    if username in userlist:
        pass
    else:
        return RedirectResponse(url='/login')
    print(action)
    dict0=eval(fname1)
    #print('fname1',fname1,type(fname1),eval(fname1),type(eval(fname1)))
    #print('running db_json')
    db = TinyDB('db/'+fname+'.json')

    User = Query()
    keys=list(dict0.keys())
    values=list(dict0.values())
    print('dict0',dict0)
    print('dict0.items()',dict0.items())
    print('hello:',User[keys[0]],values[0])
    print(db.search(User[keys[0]] == values[0]))
    if action=='删除':
        print('del')
        db.remove(User[keys[0]] == values[0])
    elif db.search(User[keys[0]] == values[0]):
        print()
        print('update')
    #for key,value in dict0.items():
    #    print(key,value)
   
        db.update(dict0, User[keys[0]] == values[0])
    else:
        if values[0]=='':
            pass
        else:
            db.insert(dict0)
    db.close()

    return RedirectResponse(url='/ok/'+fname)

@app.post("/ok/{item_id}")

def b20(item_id:str=None,username: Optional[str] = Cookie(None)):
    print(username)

    link='<a href="/ok/{item_id}">{item_id}点击刷新</a>'

    return HTMLResponse(content=link.format(item_id=item_id))
@app.get("/ok/{item_id}")

def b21(item_id:str=None,q:str='0',query:str=None):
    print('db/'+item_id+'.json')
    #print('query:',query,list(eval(query).keys())[0],list(eval(query).values())[0])

    #print(query_key,query_value)
    db = TinyDB('db/'+item_id+'.json')

    User = Query()
    if query:
        #print(db.search(User[query_key] == query_value))
        query_key=list(eval(query).keys())[0]
        query_value=list(eval(query).values())[0]
        list0=db.search(User[query_key] == query_value)
    else:
        list0=db.all()
    #print('list0',list0)
    headers=list(list0[0].keys())
   

    if q=='new':
        dictx={}
        for key in headers:
            dictx[key]=''
       
        json0=str(dictx).replace('{','{\n').replace('}','\n}').replace(',',',\n')
        return  HTMLResponse(content=html_head+json_form.format(json=json0,name=item_id))
    else:
        q=int(q)

   
    rows0=list0[1:]
    if q:
        print('*0',rows0[q-1])
        print("*1",list(rows0[q-1].values()))
        rows=[list(rows0[q-1].values())]
        #print('rows',rows())
        json0=str(rows0[q-1]).replace('{','{\n').replace('}','\n}').replace(',',',\n')
        print('json0;',json0)
        return  HTMLResponse(content=html_head+tab_html(item_id,headers,rows)+json_form.format(json=json0,name=item_id))
    else:
        #print('else')
        rows=list(map(lambda x:list(x.values()),rows0))
        json0=''
    #print(q,rows)
   

    #return  HTMLResponse(content=html1.format(tab_html(item_id,headers,rows),name=item_id,json=json0))
    return  HTMLResponse(content=html_head+tab_html(item_id,headers,rows)+'<a href="/tables_new/{}">批量excel新增/更新</a>'.format(item_id)\
                         +'&nbsp; &nbsp; &nbsp; &nbsp;<a href="/ok/{}?q=new">单个json格式新增</a>'.format(item_id))


#首页，默认跳转到表单列表
@app.get("/")

def home():
    

    return RedirectResponse(url='/list')


#列出当前存在哪些表格
@app.get("/list")

def list0():

    pathlist=os.listdir('db')
    pathlist1=list(map(lambda x:'<p><a href="/ok/{item}">{item}</a></p>'.format(item=x[:-5]),pathlist))

    return HTMLResponse(content=html_head+'<h3>当前存在列表&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
    <a href="/tables_new">建新表</a>&nbsp; &nbsp;<a href="/remove">删除表</a><h3>'+'\n'.join(pathlist1))

 
@app.get("/remove")

def b21(item_id:str=None,password:str=None,tablename:str=None):
    form='''
    <form action="?" method="get">
    <p>输入要删除的表名: <input type="text" name="tablename" /></p>
    <p>输入管理密码: <input type="text" name="password" /></p>
    <input type="submit" value="确认删除！" />
    </form>
    '''
    if password=='rootpasswd':
        #print(os.remove('db/'+tablename+'.json'))
        os.remove('db/'+tablename+'.json')
        return RedirectResponse(url='/list')
    else:
        
        return HTMLResponse(content=form)

@app.get("/test/")

def create_cookie(response: Response,q: str=None):
    value=q+"@gi-de.com"
    if value in userlist:

        response.set_cookie(key="username", value=q+"@gi-de.com", expires=100000000)
   

        return "已登录，请关闭重新打开"
    else:
        return "未获授权，请联系管理员"

email_input='''
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面，任何其他内容都*必须*跟随其后！ -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询（media queries）功能 -->
    <!-- 警告：通过 file:// 协议（就是直接将 html 页面拖拽到浏览器中）访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
   
    <h4>你好,第一次登录请正确输入自己的公司邮箱</h4>



<form action="test" method="get">



<div class="input-group" style="width:20%">
  <input type="text" class="form-control" maxlength="20" placeholder="您的邮箱" aria-describedby="basic-addon2" name=q >
  <span class="input-group-addon" id="basic-addon2">@gi-de.com</span>
</div>

<input type="submit" value="提交">
</form>

    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery，所以必须放在前边) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
  </body>
</html>
'''
@app.post("/login")
async def login(response: Response,q: str=None):
    content='''

<body>
请先登录，如果还是没有权限，请联系管理员

<a href="/login">登录</a>
</body>

    '''

    return HTMLResponse(content=email_input)


@app.get("/login")
async def login(response: Response,q: str=None):
    content='''

<body>
<h4>百度一下</h4>
<form name="input" action="test" method="get">
<input type="text" name="q">
<input type="submit" value="搜索">
</form>

</body>

    '''

    return HTMLResponse(content=email_input)

if __name__ == "__main__":
    #主程序判断是否存在数据库db文件夹，没有的话创建一个
    if os.path.exists('db'):
        pass
    else:
        os.mkdir('db')
    
    #指定fastapi的运行端口
    uvicorn.run(app, host="0.0.0.0",port=80,log_level="info")

